home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-05-25 | 28.6 KB | 789 lines | [04] ASCII Text (0x0000) |
- *******************************************************************************
- *
- * Jiffy Windows - Pixel Transfer Demonstration
- *
- * (C) Copyright Apple Computer, Inc. 1988-1990
- * All rights reserved.
- *
- * Developer Technical Support Apple II Sample Code
- *
- * by Keith Rollin
- *
- *******************************************************************************
-
- *******************************************************************************
- *
- doClose start
- *
- * Description: Closes the top window by hiding it. If it closes the last
- * window on the screen, the Close menu item is disabled.
- *
- *
- * Inputs: NONE
- *
- * Outputs: NONE
- *
- * External Refs: NONE
- *
- * Entry Points: NONE
- *
- *******************************************************************************
- using Globals
-
- ; While closing the window, we have to get a little tricky. If we are closing
- ; the Odyssey window, then we have to enable the "Read a Book" menu item. If
- ; we are closing any of the Test window, we have to enable the "Open Test
- ; Windows" menu item. We perform this check by getting the pointer to the top
- ; window, and comparing it to the stored pointer to the Odyssey window. If they
- ; match, then we know we are closing the Odyssey window. If not, then we assume
- ; that we are closing a Test window. We don't have to worry about NDA windows
- ; getting in the way as those are taken care of TaskMaster before we ever get
- ; here.
- ;
-
- pha ; get the front window
- pha
- _FrontWindow
-
- stz WindType ; Assume we're closing a test window.
-
- lda 1,s ; Check to see if we are closing
- cmp OdyWindow ; the Odyssey window
- bne HideIt
- lda 3,s
- cmp OdyWindow+2
- bne HideIt
-
- inc WindType ; set flag to say we closed Odyssey
- HideIt ANOP
- _HideWindow ; hide the top window
-
- lda WindType ; did we close a test window?
- bne EnableOdy ; no, enable "Read a Book"
-
- PushWord #258 ; yes, so re-enable that menu item
- _EnableMItem ; to let us re-open it.
- bra CheckForMoreWindows
-
- EnableOdy ANOP
- PushWord #259 ; re-enable Read A Book menu item
- _EnableMItem ; to let us re-open it.
-
- CheckForMoreWindows ANOP
- pha ; any more front windows?
- pha
- _FrontWindow
-
- plx
- pla
- bne done ; yes, so leave
- txa
- bne done ; yes, so leave
-
- PushWord #255 ; no, so disable close item
- _DisableMItem
-
- done ANOP
- rts
- WindType ds 2
- end
-
- *******************************************************************************
- *
- CacheContent start
- *
- * Description: This routine draws the contents of the window. Since it
- * is called from TaskMaster, we need to set the Direct Page
- * and Data Bank registers. The we prepare to draw the window.
- * First we check to see if there is a handle in the window's
- * RefCon, and make sure that it is not purged. If it is
- * still valid, it is used to update the window. If not, then
- * the window is drawn by hand.
- *
- *
- * Inputs: NONE
- *
- * Outputs: NONE
- *
- * External Refs:
- * Import GetOffScreenBuffer
- * Import DrawByHand
- *
- * Entry Points:
- * Export oldPort ; used by DrawByHand
- *
- *******************************************************************************
- using Globals
-
- ;
- ; CacheContents is called from the Window Manager to update the contents
- ; of the window. Therefore, the Direct Page and Data Bank Register may
- ; not be set to what our application had them set to. Save the settings
- ; as the Window Manager had them, and then set them up the way we like
- ; them. That way we can use local (2-byte absolute) addressing, and can
- ; access our Direct Page variables.
-
- phd ; Save caller's direct page
- phb ; Save caller's data bank register
-
- phk ; switch data bank to Program Bank
- plb
- lda MyDP ; switch Direct Page to application's
- tcd
-
- SetUp ANOP
-
- ; Get the port of the window that we have to update
-
- pha ; space for result of GetWRefCon
- pha
- pha ; space for result of GetPort
- pha
- _GetPort
-
- lda 1,s ; save the current port for later
- sta oldPort ; when we leave this routine. the port
- lda 3,s ; gets changed if we have to draw into
- sta oldPort+2 ; the offscreen buffer.
-
- _GetWRefCon ; Get refcon, which holds a handle to
- PullLong Deref ; the cache record.
-
- ldy #4 ; Lock the handle to the cache record.
- lda [Deref],y ; We do this using the method documented
- ora #attrLocked ; in the description of HLock in the
- sta [Deref],y ; memory manager chapter.
- dey
- dey
- lda [Deref],y ; Dereference it. Get a pointer to the
- sta CPPtr+2 ; cache record.
- lda [Deref]
- sta CPPtr
-
- ldy #4 ; See if we have cached the contents.
- lda [CPPtr],y ; We determine this by seeing if the
- iny ; pointer is a NULL pointer.
- iny
- ora [CPPtr],y ; see if the pointer is $0000 0000
- bne haveBuffer ; no it's not, so update from offscreen
-
- ; We don't have an offscreen buffer, so this is what we are going to do. First
- ; save the old port (the window that we are updating). Then, try to get an
- ; offscreen GrafPort for buffering. If that is successful, then the port will
- ; be set to it. Regardless of the outcome, however, we will draw the entire
- ; contents to whatever is active. Then we check the status of the
- ; GetOffScreenBuffer call. If it succeeded, then copy the buffer's contents
- ; to the window. If it didn't then what we drew appeared on the screen anyway,
- ; and we're done.
-
-
- lda oldPort ; pass the window pointer in X & Y
- ldx oldPort+2
- jsr GetOffScreenBuffer ; changes the port if successful
- php ; save the status of this call
- jsl DrawByHand ; draw the contents to cache or screen
-
- PushLong oldPort ; reset the port to window port
- _SetPort
-
- plp ; Did offscreen caching occur?
- bcc SetUp ; yes - now try again
- bcs done ; no - we drew to screen - so exit.
-
- haveBuffer ANOP
- ;
- ; We have an offscreen buffer. Prepare the stack for a PPToPort call.
- ;
- ldy #6 ; push on source LocInfo pointer
- PushWord [CPPtr],y ; This pointer points to the LocInfo
- dey ; of the OffScreen buffer, and is
- dey ; stored in the Cached Record.
- PushWord [CPPtr],y
-
- ;
- ; We push on a pointer to VisRect here, but haven't yet initialized it! But
- ; don't worry. We will fill in VisRect down below.
- ;
- PushLong #VisRect ; pass the pointer to the visrect.
-
- lda oldPort ; get the pointer to the dest port.
- sta Deref
- lda oldPort+2
- sta Deref+2
-
- ; Now we need to tell PPToPort what part of the screen to update. This is
- ; done by looking at the VisRgn (which contains the intersection of the
- ; update region and the VisRgn). The format of a region is:
- ;
- ; WORD: rgnSize Size of the region
- ; RECT: rgnBBox rectangle the just surrounds the region
- ; XXXX: rgnData region data the would get me fired if I told you what it was.
- ;
- ; By using rgnBBox as our source/destination rectangle, we make PPToPort do
- ; as little work as possible; There won't be anything to update outside of
- ; that rectangle.
- ;
- ldy #ovisRgn+2 ; Find the visible rectangle.
- lda [Deref],y ; First get the handle to the visRgn.
- sta temp2+2
- dey
- dey
- lda [Deref],y
- sta temp2
-
- ldy #2 ; Deref the VisRgn handle
- lda [temp2],y
- sta temp1+2
- lda [temp2]
- sta temp1
-
- ldy #8 ; finally copy the rect out of the
- loop lda [temp1],y ; VisRgn into a local variable.
- sta VisRect-2,y
- dey
- dey
- bne loop
-
- ;
- ; VisRect now holds the rectangle that surrounds the entire area to udpate.
- ; This makes that "PushLong #VisRect" above point to valid data!
- ;
- ; Now we push on the destination for the PPToPort command. Since PPToPort
- ; doesn't do any scaling, all we need is the upper-left hand point of the
- ; destination; the lower left corner is calculated by QuickDraw by using the
- ; height and width of the source.
-
- PushLong VisRect ; use the upper left hand corner of the
- * ; source rectangle as the destination.
-
- PushWord #modeCopy ; Set the transfer mode.
- _PPToPort ; Blit those bits!!!
-
- pha ; push on room for GetWRefcon result
- pha
- PushLong oldPort
- _GetWRefCon
- _HUnlock ; unlock the Cache record handle
-
- done ANOP
- plb ; restore caller's data bank register
- pld ; restore caller's direct page reg.
-
- rtl ; return to TaskMaster
-
- oldPort entry
- ds 4
- VisRect ds 8
-
- end
-
- EJECT
- *******************************************************************************
- *
- SlowDraw start
- *
- * Description: This routine calls the routine that draws the test window
- * contents. It takes the place of the 'CacheContents'
- * routine for Windows 1 and 2. It does NOT cache the window
- * contents, and is used to show the difference between
- * cached and non-cached updating.
- *
- *
- * Inputs:
- *
- * Outputs:
- *
- * External Refs:
- * Import DrawContent
- *
- * Entry Points:
- *
- *******************************************************************************
- using Globals
-
- ;
- ; SlowDraw is called from the Window Manager to update the contents
- ; of the window. Therefore, the Direct Page and Data Bank Register may
- ; not be set to what our application had them set to. Save the settings
- ; as the Window Manager had them, and then set them up the way we like
- ; them. That way we can use local (2-byte absolute) addressing, and can
- ; access our Direct Page variables.
- ;
- phd
- phb
-
- phk
- plb
- lda MyDP
- tcd
-
- pha
- pha
- _GetPort
- pla
- plx
-
- jsl DrawContent
-
- plb
- pld
-
- rtl
- end
-
- EJECT
- *******************************************************************************
- *
- DrawByHand start
- *
- * Description: The contents need to be created for the first time. The
- * address of theroutine that doesthis is in a parameter
- * block pointed to by the RefCon. Get this address, push it
- * on the stack, and load up A and X with the pointer to the
- * window so that the drawing routine can have information
- * about it (the actual port it is drawing to is an offscreen
- * port, and does not have window information in it, like the
- * window title).
- *
- *
- * Inputs: NONE
- *
- * Outputs: NONE
- *
- * External Refs:
- * Import oldPort
- *
- * Entry Points: NONE
- *
- *******************************************************************************
- using Globals
-
- ldy #1 ; Get bytes 1 and 2 of drawing routine.
- PushWord [CPPtr],y ; push bytes 1 and 2 on.
- phb ; push one byte onto the stack.
- lda [CPPtr] ; Get bytes 0 and 1 into Acc.
- sta 1,s ; now store bytes 0 and 1 on the stack
- lda oldPort ; set up A & X for the drawing routine
- ldx oldPort+2
- rtl ; RTL to the drawing routine
-
- end
-
- EJECT
- *******************************************************************************
- *
- DrawOdyRtn start
- *
- * Description: This routine posts the first few pages of Sculley's book
- * into the Cache buffer or onto the screen. It uses TextBox2
- * and takes a while, so tell the user by showing a watch.
- *
- * None of what I do here requires the use of my Direct Page
- * or 2-byte absolute addressing, so I don't need to change
- * the Direct Page or Data Bank Registers. However, other
- * routines that perform updating will normally need to change
- * these. The CacheContents routine demonstrates the
- * technique.
- *
- *
- * Inputs: A = low order word of window pointer
- * X = high order word
- *
- * Outputs: NONE
- *
- * External Refs: NONE
- *
- * Entry Points: NONE
- *
- *******************************************************************************
- using Globals
-
- ;
- ; --- We'll be sitting here for a while, so tell the user.
- ;
- _WaitCursor
-
- jsl xorPoint
- PushLong #Odyssey ; push pointer to text
- PushWord #OdysseyEnd-Odyssey ; length of text
- PushLong #OdyRect ; bounds to fit the text into
- PushWord #0 ; Fill justify
- _LETextBox2 ; draw it all!
-
- _InitCursor ; set cursor back to arrow.
-
- * This routine is necessary to work around a bug in system disk 5.0. The fastFont
- * routine has a problem with pixelmaps that are larger than 64k. The fastFont
- * routine is used only when the regions are rectangular and no region clipping
- * is involved. If either the clipRgn or visRgn is not rectangular, then fastFont
- * is not used. This method of "turning it off" is what we will use to work around
- * the bug. Note that the visRgn is made non-rectangular. This would normally
- * be a bad thing. However, setting the clipRgn non-rectangular does not work in
- * this case because LETextBox2 sets the clipRgn to a rectangular region the size
- * of the rectangle for the text. So, setting the clipRgn to be non-rectangular
- * is defeated by the LETextBox2 routine. This is why the visRgn is used.
- * Also note that for off-screen grafPorts, the visRgn IS your property, so it
- * is okay to modify it. Also note that the modification to the visRgn is undone
- * after the LETextBox2 call.
-
- xorPoint pha
- pha
- _NewRgn ; Temp region handle now on stack.
-
- lda 3,s ; Duplicate region handle on stack.
- pha
- lda 3,s
- pha
-
- ldy #-1 ; Push rect of -1,-1,0,0
- phy
- phy
- iny
- phy
- phy
- _SetRectRgn ; Temp region handle still on stack.
-
- lda 3,s ; Duplicate region handle on stack.
- pha
- lda 3,s
- pha
-
- pha
- pha
- _GetVisHandle ; visRgn handle on stack.
-
- lda 3,s ; Duplicate visRgn handle on stack.
- pha
- lda 3,s
- pha
-
- _XorRgn ; Xor point in visRgn.
- _DisposeRgn ; Dispose of visRgn.
-
- rtl ; Back to caller.
-
- OdyRect dc i2'0,10,790,590'
-
- end
-
- EJECT
- *******************************************************************************
- *
- DrawContent start
- *
- * Description: This is the real procedure that draws the contents of the
- * Test windows. It merely draws the name of the window many
- * times.
- *
- *
- * Inputs: A = low order word of window pointer
- * X = high order word
- *
- * Outputs: NONE
- *
- * External Refs: NONE
- *
- * Entry Points: NONE
- *
- *******************************************************************************
- using Globals
-
- sta myPort ; save window pointer
- stx myPort+2
-
- pha ; room for window title pointer
- pha
- phx ; push on window pointer
- pha
- _GetWTitle ; get the window's title
- PullLong wTitle
-
- lda #10 ; now initialize the X and Y variables
- sta yLoc ; that we use to draw the strings.
- lda #0
- sta xLoc
- lda #10 ; loop 10 times down the screen
- sta bigCounter
- loop ANOP
- PushWord xLoc ; set up for the Moveto
- PushWord yLoc
- _MoveTo
-
- lda #8 ; loop 8 times across the screen
- sta littleCounter
- loop2 ANOP
- PushLong wTitle ; put window title pointer onto stack
- _DrawString ; and draw the string
- dec littleCounter ; update our horizontal counter
- bpl loop2
-
- lda yLoc ; update the X/Y coordinates
- clc
- adc #10
- sta yLoc
- lda xLoc
- sec
- sbc #20
- sta xLoc
- dec bigCounter ; update our vertical counter
- bpl loop ; ...and check it.
-
- rtl
-
- xLoc ds 2 ; where to start drawing string next
- yLoc ds 2 ; where to start drawing string next
- littleCounter ds 2 ; counter across the screen
- bigCounter ds 2 ; counter down the screen
-
- myPort ds 4
- wTitle ds 4
-
- end
-
- EJECT
- *******************************************************************************
- *
- GetOffScreenBuffer start
- *
- * Description: Get a handle to an offscreen GrafPort. If _NewHandle call
- * fails, set the carry and return. If it succeeds, create a
- * new bitmap for it, install the bitmap, and initialize the
- * appropriate fields. Finally, install the pointer to the
- * GrafPort in the cache record for the window, clear the
- * carry, and return with the port set to the new port.
- *
- * This routine is entered with the pointer to the window
- * manager port of the window we are updating. In case we
- * cannot get an offscreen buffer, we can reset the port to
- * this.
- *
- *
- * Inputs: A = low word of window pointer of window we are updating
- * X = high word
- *
- * Outputs: NONE
- *
- * External Refs: NONE
- *
- * Entry Points: NONE
- *
- *******************************************************************************
- using Globals
-
- sta origPort ; save the window manager port
- stx origPort+2
-
- ;
- ; --- Get a memory for a new grafport
- ;
- stz newPort ; assume that we don't get it.
- stz newPort+2
- pha ; space for the new handle
- pha
- PushLong #portSize
- PushWord MyID
- PushWord #attrFixed ; plus 'attrNoCross' if on old ROMs
- PushLong #$0000
- _NewHandle
- PullLong Deref
- bcs error
-
- ldy #2 ; Dereference and lose the handle
- lda [Deref],y ; (we only need a pointer)
- tax
- lda [Deref]
- sta newPort
- stx newPort+2
-
- phx ; Now initialize it as a GrafPort
- pha
- _OpenPort
- bcs error
- ;
- ; --- We now have a port to play with, but its PixImage is the
- ; --- screen. Let's change that.
- ;
- jsr AddPixMap
- bcs error
-
- ; Everything is all set up. The current port should still be the one
- ; we just created with the _OpenPort above. All we have to do is install
- ; the pointer to it into the cacheParms block for the Window.
-
- ldy #4
- lda newPort
- sta [CPPtr],y
- iny
- iny
- lda newPort+2
- sta [CPPtr],y
-
- clc
- rts
- error ANOP
- pha ; Error occured. Get the handle to the
- pha ; port that we created; dispose of it.
- PushLong newPort
- _FindHandle
- bcs skip
- _DisposeHandle
- skip ANOP
- PushLong origPort
- _SetPort
- sec
- rts
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;
- ; This routine adds an offscreen PixMap to the Grafport pointed to by
- ; 'newPort'.
- ;
- AddPixMap ANOP
- jsr CalcScrnDims ; get values for LocInfo
-
- pha ; get a PixImagePtr of right size
- pha
- PushLong scrnSize
- PushWord MyID
- PushWord #attrFixed ; plus 'attrNoCross' if on old ROMs
- PushLong #$0000
- _NewHandle
- PullLong Deref
- bcs error2
-
- ;
- ; Get the Window Pointer into a Direct Page location (temp1) for
- ; easy access later.
- ;
- lda newPort
- sta temp1
- lda newPort+2
- sta temp1+2
-
- ldy #2 ; Dereference and lose the handle
- lda [Deref],y ; to the PixImage (it's locked)
- tax
- lda [Deref] ; (pointer in A and X)
-
- ldy #optrToPixImage ; install the new PixImage
- sta [temp1],y
- iny
- iny
- txa
- sta [temp1],y
-
- ldy #owidth ; set the 'rowBytes' value
- lda rowBytes
- sta [temp1],y
-
- ldy #oboundsRect+4 ; update the size of the boundsRect
- lda scrnHeight
- sta [temp1],y
- iny
- iny
- lda scrnWidth
- sta [temp1],y
-
- ldy #oportRect+4 ; and the size of the portrect
- lda scrnHeight
- sta [temp1],y
- iny
- iny
- lda scrnWidth
- sta [temp1],y
-
- ;
- ; Set the VisRgn and ClipRgn to the size of the port we just
- ; created. This is done by calling ClipRect with the portRect,
- ; and then copying the resulting ClipRgn to the VisRgn.
- ;
- lda temp1 ; Create a pointer to the portRect
- clc ; in the Window Record (remember,
- adc #oportRect ; temp1 points to the WindRec).
- tax
- lda temp1+2
- adc #0
- pha ; push on one set for _EraseRect
- phx
- pha ; push on this set for _ClipRect
- phx
- _ClipRect
-
- ldy #oclipRgn+2 ; now copy the ClipRgn to the VisRgn
- PushWord [temp1],y
- dey
- dey
- PushWord [temp1],y
- _SetVisRgn
-
- _EraseRect ; rect ptr left on from way before.
-
- clc
- rts
-
- error2 ANOP
- sec
- rts
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;
- ; Calculate the screen size based on the general formula:
- ;
- ; rowBytes := (((((right - left) * theDepth) + 7) DIV 8) + 7) AND ~%111
- ;
- ; in English, or what passes for it when I type, this says: take the width
- ; of the GrafPort, and multiply it by the depth (number of bits per pixel)
- ; of the screen. Add 7 to this and divide by 8 to get the number of bytes
- ; that this takes up (add 7 effectively rounds up, to counter the DIV 8's
- ; rounding down). After we have the number of bytes, we have to make sure that
- ; this is an "even multiple of 8", as it states in the QuickDraw Chapter. This
- ; is done by adding 7 (again, to round up) and stripping off the low 3 bits,
- ; which performs the rounding down to the nearest multiple of 8.
- ;
- ; This formula can be slightly reduced to:
- ;
- ; rowBytes := ((((right - left) * theDepth) + 63) DIV 8) AND ~%111
- ;
- ; which is used in specific:
- ;
- ; rowBytes := (((scrnWidth * 2) + 63) DIV 8) AND ~%111
- ;
- CalcScrnDims ANOP
- ldy #10 ; get the screen width from cacheParms
- lda [CPPtr],y
- sta scrnWidth
- asl a ; times 2
- ; asl a ; use this also if in 320 mode
- clc ; add 63
- adc #63
- lsr a ; divide by 8
- lsr a
- lsr a
- and #%11111000 ; and with ~%111
- sta rowBytes
- pha ; Now prepare to multiply to get
- pha ; the whole screen size.
- pha ; Multiplier
- dey
- dey
- lda [CPPtr],y
- sta scrnHeight
- pha ; Multiplicand
- _Multiply
- PullLong scrnSize
- rts
-
- origPort ds 4
- newPort ds 4
-
- scrnSize ds 4
- scrnHeight ds 2
- scrnWidth ds 2
- rowBytes ds 2
-
- end
-
- copy Jiffy.stds.asm
-
- END
-